"""
工具函数模块
"""
import json
import hashlib
import logging
from typing import Dict, Any, Optional, Tuple
from functools import lru_cache

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


def generate_cache_key(code: str, language: str, context: Optional[str] = None) -> str:
    """
    生成缓存键
    
    Args:
        code: 代码内容
        language: 编程语言
        context: 上下文信息
    
    Returns:
        缓存键字符串
    """
    content = f"{code}:{language}:{context or ''}"
    return hashlib.md5(content.encode('utf-8')).hexdigest()


def parse_json_response(response_text: str) -> Dict[str, Any]:
    """
    解析JSON响应，处理可能的格式问题
    
    Args:
        response_text: AI返回的文本
    
    Returns:
        解析后的JSON字典
    """
    try:
        # 尝试直接解析
        return json.loads(response_text)
    except json.JSONDecodeError:
        # 如果直接解析失败，尝试提取JSON部分
        try:
            # 查找第一个 { 和最后一个 }
            start = response_text.find('{')
            end = response_text.rfind('}') + 1
            if start >= 0 and end > start:
                return json.loads(response_text[start:end])
        except json.JSONDecodeError:
            pass
        
        # 如果还是失败，尝试查找代码块中的JSON
        try:
            if '```json' in response_text:
                start = response_text.find('```json') + 7
                end = response_text.find('```', start)
                if end > start:
                    return json.loads(response_text[start:end].strip())
            elif '```' in response_text:
                start = response_text.find('```') + 3
                end = response_text.find('```', start)
                if end > start:
                    return json.loads(response_text[start:end].strip())
        except json.JSONDecodeError:
            pass
        
        logger.warning(f"无法解析JSON响应: {response_text[:200]}")
        # 返回一个默认的错误响应
        return {
            "error": "无法解析AI响应",
            "raw_response": response_text[:500]
        }


def validate_code_input(code: str, language: str) -> Tuple[bool, Optional[str]]:
    """
    验证代码输入
    
    Args:
        code: 代码内容
        language: 编程语言
    
    Returns:
        (是否有效, 错误信息)
    """
    if not code or not code.strip():
        return False, "代码内容不能为空"
    
    if len(code) > 50000:  # 限制代码长度
        return False, "代码内容过长，请限制在50000字符以内"
    
    if language not in [
        "python", "javascript", "typescript", "java",
        "go", "rust", "cpp", "c", "php", "ruby"
    ]:
        return False, f"不支持的编程语言: {language}"
    
    return True, None


def format_quality_report(report: Dict[str, Any]) -> str:
    """
    格式化质量报告为可读的字符串
    
    Args:
        report: 质量报告字典
    
    Returns:
        格式化后的字符串
    """
    if "error" in report:
        return f"错误: {report.get('error', '未知错误')}"
    
    score = report.get("score", 0)
    issues = report.get("issues", [])
    strengths = report.get("strengths", [])
    improvements = report.get("improvements", [])
    
    result = f"代码质量评分: {score}/100\n\n"
    
    if strengths:
        result += "代码优点:\n"
        for strength in strengths:
            result += f"  ✓ {strength}\n"
        result += "\n"
    
    if issues:
        result += f"发现 {len(issues)} 个问题:\n"
        for issue in issues:
            severity = issue.get("severity", "unknown")
            issue_type = issue.get("type", "unknown")
            description = issue.get("description", "")
            suggestion = issue.get("suggestion", "")
            line = issue.get("line", "")
            
            severity_icon = {
                "critical": "🔴",
                "high": "🟠",
                "medium": "🟡",
                "low": "🟢"
            }.get(severity, "⚪")
            
            result += f"\n{severity_icon} [{severity.upper()}] {issue_type}"
            if line:
                result += f" (第 {line} 行)"
            result += f"\n   问题: {description}"
            if suggestion:
                result += f"\n   建议: {suggestion}\n"
    
    if improvements:
        result += "\n改进建议:\n"
        for improvement in improvements:
            result += f"  • {improvement}\n"
    
    return result


def get_language_extension(language: str) -> str:
    """
    获取编程语言的文件扩展名
    
    Args:
        language: 编程语言名称
    
    Returns:
        文件扩展名
    """
    extensions = {
        "python": ".py",
        "javascript": ".js",
        "typescript": ".ts",
        "java": ".java",
        "go": ".go",
        "rust": ".rs",
        "cpp": ".cpp",
        "c": ".c",
        "php": ".php",
        "ruby": ".rb"
    }
    return extensions.get(language.lower(), ".txt")


def format_refactoring_suggestions(result: Dict[str, Any], language: str = "python") -> str:
    """
    格式化重构建议为Markdown格式，包含代码高亮
    
    Args:
        result: 重构建议结果字典
        language: 编程语言
    
    Returns:
        Markdown格式的字符串
    """
    if "error" in result:
        return f"## 错误\n\n{result.get('error', '未知错误')}"
    
    md = []
    md.append("## 重构建议\n\n")
    
    refactoring_type = result.get("refactoring_type", "通用重构")
    md.append(f"**重构类型**: {refactoring_type}\n\n")
    
    current_issues = result.get("current_issues", [])
    if current_issues:
        md.append("### 当前问题\n\n")
        for issue in current_issues:
            md.append(f"- {issue}\n")
        md.append("\n")
    
    suggestions = result.get("suggestions", [])
    if suggestions:
        md.append("### 重构建议详情\n\n")
        for idx, suggestion in enumerate(suggestions, 1):
            md.append(f"#### 建议 {idx}: {suggestion.get('description', '重构建议')}\n\n")
            
            benefit = suggestion.get("benefit", "")
            if benefit:
                md.append(f"**预期收益**: {benefit}\n\n")
            
            # 重构前的代码
            code_before = suggestion.get("code_before") or suggestion.get("example_before", "")
            if code_before:
                md.append("**重构前的代码**:\n\n")
                md.append(f"```{language}\n{code_before}\n```\n\n")
            
            # 重构后的代码
            code_after = suggestion.get("code_after") or suggestion.get("example_after", "")
            if code_after:
                md.append("**重构后的代码**:\n\n")
                md.append(f"```{language}\n{code_after}\n```\n\n")
            
            # 关键变更点
            key_changes = suggestion.get("key_changes", [])
            if key_changes:
                md.append("**关键变更点**:\n\n")
                for change in key_changes:
                    md.append(f"- {change}\n")
                md.append("\n")
            
            md.append("---\n\n")
    
    return "".join(md)


def format_test_cases(result: Dict[str, Any], language: str = "python", test_framework: str = "default") -> str:
    """
    格式化测试用例为Markdown格式，包含代码高亮
    
    Args:
        result: 测试用例结果字典
        language: 编程语言
        test_framework: 测试框架
    
    Returns:
        Markdown格式的字符串
    """
    if "error" in result:
        return f"## 错误\n\n{result.get('error', '未知错误')}"
    
    md = []
    md.append("## 测试用例建议\n\n")
    
    # 确定代码块语言
    code_lang = language
    if language == "python" and test_framework in ["pytest", "unittest"]:
        code_lang = "python"
    elif language == "javascript" and test_framework in ["jest", "mocha"]:
        code_lang = "javascript"
    elif language == "java" and test_framework in ["junit", "testng"]:
        code_lang = "java"
    
    test_cases = result.get("test_cases", [])
    if test_cases:
        md.append("### 测试用例\n\n")
        for idx, test_case in enumerate(test_cases, 1):
            name = test_case.get("name", f"测试用例 {idx}")
            description = test_case.get("description", "")
            scenario = test_case.get("scenario", "")
            test_code = test_case.get("test_code", "")
            
            md.append(f"#### {idx}. {name}\n\n")
            
            if description:
                md.append(f"**描述**: {description}\n\n")
            
            if scenario:
                scenario_map = {
                    "normal": "正常情况",
                    "boundary": "边界情况",
                    "exception": "异常情况"
                }
                scenario_text = scenario_map.get(scenario.lower(), scenario)
                md.append(f"**测试场景**: {scenario_text}\n\n")
            
            if test_code:
                md.append("**测试代码**:\n\n")
                md.append(f"```{code_lang}\n{test_code}\n```\n\n")
            else:
                # 如果没有test_code，尝试从其他字段构建
                input_data = test_case.get("input", "")
                expected_output = test_case.get("expected_output", "")
                if input_data or expected_output:
                    md.append("**测试信息**:\n\n")
                    if input_data:
                        md.append(f"- 输入: {input_data}\n")
                    if expected_output:
                        md.append(f"- 预期输出: {expected_output}\n")
                    md.append("\n")
            
            md.append("---\n\n")
    
    # 覆盖率分析
    coverage = result.get("coverage_analysis", {})
    if coverage:
        md.append("### 覆盖率分析\n\n")
        
        covered = coverage.get("covered", [])
        if covered:
            md.append("**已覆盖的功能点**:\n\n")
            for item in covered:
                md.append(f"- ✓ {item}\n")
            md.append("\n")
        
        missing = coverage.get("missing", [])
        if missing:
            md.append("**缺失的测试场景**:\n\n")
            for item in missing:
                md.append(f"- ✗ {item}\n")
            md.append("\n")
    
    return "".join(md)

